home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / pathalias10 / part02 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  53.6 KB

  1. Subject:  v22i110:  Pathalias, version 10, Part02/03
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: ee393bfd 87611971 deb30f87 0dbfdbfd
  5.  
  6. Submitted-by: peter honeyman <honey@citi.umich.edu>
  7. Posting-number: Volume 22, Issue 110
  8. Archive-name: pathalias10/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  addlink.c addnode.c arpa-privates mapaux.c parse.y
  17. #   printit.c
  18. # Wrapped by rsalz@litchi.bbn.com on Fri Jun  8 09:25:21 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. echo If this archive is complete, you will see the following message:
  21. echo '          "shar: End of archive 2 (of 3)."'
  22. if test -f 'addlink.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'addlink.c'\"
  24. else
  25.   echo shar: Extracting \"'addlink.c'\" \(6001 characters\)
  26.   sed "s/^X//" >'addlink.c' <<'END_OF_FILE'
  27. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  28. X#ifndef lint
  29. Xstatic char    *sccsid = "@(#)addlink.c    9.7 88/06/10";
  30. X#endif /* lint */
  31. X
  32. X#include "def.h"
  33. X
  34. X/* exports */
  35. Xextern link *addlink();
  36. Xextern void deadlink(), atrace(), freelink();
  37. Xextern int tracelink(), maptrace();
  38. Xchar *Netchars = "!:@%";    /* sparse, but sufficient */
  39. Xlong Lcount;            /* how many edges? */
  40. X
  41. X/* imports */
  42. Xextern int Tflag, Dflag;
  43. Xextern link *newlink();
  44. Xextern node *addnode();
  45. Xextern void yyerror(), die();
  46. Xextern int strcmp(), strlen();
  47. X
  48. X/* privates */
  49. XSTATIC void netbits(), ltrace(), ltrprint();
  50. Xstatic link    *Trace[NTRACE];
  51. Xstatic int    Tracecount;
  52. X
  53. X#define EQ(n1, n2)    (strcmp((n1)->n_name, (n2)->n_name) == 0)
  54. X#define LTRACE        if (Tflag) ltrace
  55. X
  56. Xlink *
  57. Xaddlink(from, to, cost, netchar, netdir)
  58. X    node *from;
  59. X    register node *to;
  60. X    Cost cost;
  61. X    char netchar, netdir;
  62. X{    register link *l, *prev = 0;
  63. X
  64. X    LTRACE(from, to, cost, netchar, netdir, "");
  65. X    /*
  66. X     * maintain uniqueness for dead links (only).
  67. X     */
  68. X    for (l = from->n_link; l; l = l->l_next) {
  69. X        if (!DEADLINK(l))
  70. X            break;
  71. X        if (to == l->l_to) {
  72. X            /* what the hell, use cheaper dead cost */
  73. X            if (cost < l->l_cost) {
  74. X                l->l_cost = cost;
  75. X                netbits(l, netchar, netdir);
  76. X            }
  77. X            return l;
  78. X        }
  79. X        prev = l;
  80. X    }
  81. X    
  82. X
  83. X    /* allocate and link in the new link struct */
  84. X    l = newlink();
  85. X    if (cost != INF)    /* ignore back links */
  86. X        Lcount++;
  87. X    if (prev) {
  88. X        l->l_next = prev->l_next;
  89. X        prev->l_next = l;
  90. X    } else {
  91. X        l->l_next = from->n_link;
  92. X        from->n_link = l;
  93. X    }
  94. X
  95. X    l->l_to = to;
  96. X    /* add penalty */
  97. X    if ((l->l_cost = cost + from->n_cost) < 0) {
  98. X        char buf[100];
  99. X
  100. X        l->l_flag |= LDEAD;
  101. X        sprintf(buf, "link to %s ignored with negative cost", to->n_name);
  102. X        yyerror(buf);
  103. X    }
  104. X    if (netchar == 0) {
  105. X        netchar = DEFNET;
  106. X        netdir = DEFDIR;
  107. X    }
  108. X    netbits(l, netchar, netdir);
  109. X    if (Dflag && ISADOMAIN(from))
  110. X        l->l_flag |= LTERMINAL;
  111. X
  112. X    return l;
  113. X}
  114. X
  115. Xvoid
  116. Xdeadlink(nleft, nright) 
  117. X    node *nleft, *nright;
  118. X{    link *l, *lhold = 0, *lprev, *lnext;
  119. X
  120. X    /* DEAD host */
  121. X    if (nright == 0) {
  122. X        nleft->n_flag |= NDEAD;        /* DEAD host */
  123. X        return;
  124. X    }
  125. X
  126. X    /* DEAD link */
  127. X
  128. X    /* grab <nleft, nright> instances at head of nleft adjacency list */
  129. X    while ((l = nleft->n_link) != 0 && l->l_to == nright) {
  130. X        nleft->n_link = l->l_next;    /* disconnect */
  131. X        l->l_next = lhold;        /* terminate */
  132. X        lhold = l;            /* add to lhold */
  133. X    }
  134. X
  135. X    /* move remaining <nleft, nright> instances */
  136. X    for (lprev = nleft->n_link; lprev && lprev->l_next; lprev = lprev->l_next) {
  137. X        if (lprev->l_next->l_to == nright) {
  138. X            l = lprev->l_next;
  139. X            lprev->l_next = l->l_next;    /* disconnect */
  140. X            l->l_next = lhold;        /* terminate */
  141. X            lhold = l;
  142. X        }
  143. X    }
  144. X
  145. X    /* check for emptiness */
  146. X    if (lhold == 0) {
  147. X        addlink(nleft, nright, INF / 2, DEFNET, DEFDIR)->l_flag |= LDEAD;
  148. X        return;
  149. X    }
  150. X
  151. X    /* reinsert deleted edges as DEAD links */
  152. X    for (l = lhold; l; l = lnext) {
  153. X        lnext = l->l_next;
  154. X        addlink(nleft, nright, l->l_cost, NETCHAR(l), NETDIR(l))->l_flag |= LDEAD;
  155. X        freelink(l);
  156. X    }
  157. X}
  158. X
  159. XSTATIC void
  160. Xnetbits(l, netchar, netdir)
  161. X    register link *l;
  162. X    char netchar, netdir;
  163. X{
  164. X    l->l_flag &= ~LDIR;
  165. X    l->l_flag |= netdir;
  166. X    l->l_netop = netchar;
  167. X}
  168. X
  169. Xint
  170. Xtracelink(arg) 
  171. X    char *arg;
  172. X{    char *bang;
  173. X    link *l;
  174. X
  175. X    if (Tracecount >= NTRACE)
  176. X        return -1;
  177. X    l = newlink();
  178. X    bang = index(arg, '!');
  179. X    if (bang) {
  180. X        *bang = 0;
  181. X        l->l_to = addnode(bang+1);
  182. X    } else 
  183. X        l->l_to = 0;
  184. X
  185. X    l->l_from = addnode(arg);
  186. X    Trace[Tracecount++] = l;
  187. X    return 0;
  188. X}
  189. X
  190. X/*
  191. X * the obvious choice for testing equality is to compare struct
  192. X * addresses, but that misses private nodes, so we use strcmp().
  193. X */
  194. X
  195. XSTATIC void
  196. Xltrace(from, to, cost, netchar, netdir, message)
  197. X    node *from, *to;
  198. X    Cost cost;
  199. X    char netchar, netdir, *message;
  200. X{    link *l;
  201. X    int i;
  202. X
  203. X    for (i = 0; i < Tracecount; i++) {
  204. X        l = Trace[i];
  205. X        /* overkill, but you asked for it! */
  206. X        if (l->l_to == 0) {
  207. X            if (EQ(from, l->l_from) || EQ(to, l->l_from))
  208. X                break;
  209. X        } else if (EQ(from, l->l_from) && EQ(to, l->l_to))
  210. X            break;
  211. X        else if (EQ(from, l->l_to) && EQ(to, l->l_from))
  212. X            break;    /* potential dead backlink */
  213. X    }
  214. X    if (i < Tracecount)
  215. X        ltrprint(from, to, cost, netchar, netdir, message);
  216. X}
  217. X
  218. X/* print a trace item */
  219. XSTATIC void
  220. Xltrprint(from, to, cost, netchar, netdir, message)
  221. X    node *from, *to;
  222. X    Cost cost;
  223. X    char netchar, netdir, *message;
  224. X{    char buf[256], *bptr = buf;
  225. X
  226. X    strcpy(bptr, from->n_name);
  227. X    bptr += strlen(bptr);
  228. X    *bptr++ = ' ';
  229. X    if (netdir == LRIGHT)            /* @% */
  230. X        *bptr++ = netchar;
  231. X    strcpy(bptr, to->n_name);
  232. X    bptr += strlen(bptr);
  233. X    if (netdir == LLEFT)            /* !: */
  234. X        *bptr++ = netchar;
  235. X    sprintf(bptr, "(%ld) %s", cost, message);
  236. X    yyerror(buf);
  237. X}
  238. X
  239. Xvoid
  240. Xatrace(n1, n2)
  241. X    node *n1, *n2;
  242. X{    link *l;
  243. X    int i;
  244. X    char buf[256];
  245. X
  246. X    for (i = 0; i < Tracecount; i++) {
  247. X        l = Trace[i];
  248. X        if (l->l_to == 0 && ((node *) l->l_from == n1 || (node *) l->l_from == n2)) {
  249. X            sprintf(buf, "%s = %s", n1->n_name, n2->n_name);
  250. X            yyerror(buf);
  251. X            return;
  252. X        }
  253. X    }
  254. X}
  255. X
  256. Xint
  257. Xmaptrace(from, to)
  258. X    register node *from, *to;
  259. X{    register link *l;
  260. X    register int i;
  261. X
  262. X    for (i = 0; i < Tracecount; i++) {
  263. X        l = Trace[i];
  264. X        if (l->l_to == 0) {
  265. X            if (EQ(from, l->l_from) || EQ(to, l->l_from))
  266. X                return 1;
  267. X        } else if (EQ(from, l->l_from) && EQ(to, l->l_to))
  268. X                return 1;
  269. X    }
  270. X    return 0;
  271. X}
  272. X
  273. Xvoid
  274. Xdeletelink(from, to)
  275. X    node *from;
  276. X    node *to;
  277. X{    register link *l, *lnext;
  278. X
  279. X    l = from->n_link;
  280. X
  281. X    /* delete all neighbors of from */
  282. X    if (to == 0) {
  283. X        while (l) {
  284. X            LTRACE(from, l->l_to, l->l_cost, NETCHAR(l), NETDIR(l), "DELETED");
  285. X            lnext = l->l_next;
  286. X            freelink(l);
  287. X            l = lnext;
  288. X        }
  289. X        from->n_link = 0;
  290. X        return;
  291. X    }
  292. X
  293. X    /* delete from head of list */
  294. X    while (l && EQ(to, l->l_to)) {
  295. X        LTRACE(from, to, l->l_cost, NETCHAR(l), NETDIR(l), "DELETED");
  296. X        lnext = l->l_next;
  297. X        freelink(l);
  298. X        l = from->n_link = lnext;
  299. X    }
  300. X
  301. X    /* delete from interior of list */
  302. X    if (l == 0)
  303. X        return;
  304. X    for (lnext = l->l_next; lnext; lnext = l->l_next) {
  305. X        if (EQ(to, lnext->l_to)) {
  306. X            LTRACE(from, to, l->l_cost, NETCHAR(l), NETDIR(l), "DELETED");
  307. X            l->l_next = lnext->l_next;
  308. X            freelink(lnext);
  309. X            /* continue processing this link */
  310. X        } else
  311. X            l = lnext;    /* next link */
  312. X    }
  313. X}
  314. END_OF_FILE
  315.   if test 6001 -ne `wc -c <'addlink.c'`; then
  316.     echo shar: \"'addlink.c'\" unpacked with wrong size!
  317.   fi
  318.   # end of 'addlink.c'
  319. fi
  320. if test -f 'addnode.c' -a "${1}" != "-c" ; then 
  321.   echo shar: Will not clobber existing file \"'addnode.c'\"
  322. else
  323.   echo shar: Extracting \"'addnode.c'\" \(8979 characters\)
  324.   sed "s/^X//" >'addnode.c' <<'END_OF_FILE'
  325. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  326. X#ifndef lint
  327. Xstatic char    *sccsid = "@(#)addnode.c    9.6 89/05/05";
  328. X#endif
  329. X
  330. X#include "def.h"
  331. X
  332. X#define EQ(n, s)    (*(n)->n_name == *(s) && strcmp((n)->n_name, (s)) == 0)
  333. X
  334. X/* exports */
  335. Xnode *addnode(), *addprivate();
  336. Xvoid alias(), hashanalyze(), fixprivate();
  337. Xnode **Table;                /* hash table ^ priority queue */
  338. Xlong Tabsize;                /* size of Table */    
  339. X
  340. X/* imports */
  341. Xextern link *addlink();
  342. Xextern node *newnode(), **newtable();
  343. Xextern char *strsave();
  344. Xextern int Iflag, Tflag, Vflag;
  345. Xextern node **Table;
  346. Xextern long Ncount, Tabsize;
  347. Xextern char **Argv;
  348. Xextern void atrace(), die(), freetable();
  349. Xextern int strcmp();
  350. X
  351. X/* privates */
  352. XSTATIC void crcinit(), rehash(), lowercase();
  353. XSTATIC long fold();
  354. XSTATIC long hash();
  355. XSTATIC node *isprivate();
  356. Xstatic node *Private;    /* list of private nodes in current input file */
  357. X/*
  358. X * these numbers are chosen because:
  359. X *    -> they are prime,
  360. X *    -> they are monotonic increasing,
  361. X *    -> each is a tad smaller than a multiple of 1024,
  362. X *    -> they form a fibonacci sequence (almost).
  363. X * the first point yields good hash functions, the second is used for the
  364. X * standard re-hashing implementation of open addressing, the third
  365. X * optimizes for quirks in some mallocs i have seen, and the fourth simply
  366. X * appeals to me.
  367. X */
  368. Xstatic long Primes[] = {
  369. X    1021, 2039, 3067, 5113, 8179, 13309, 21499, 34807, 56311, 0
  370. X};
  371. X
  372. Xstatic int    Tabindex;
  373. Xstatic long    Tab128;        /* Tabsize * 128 */
  374. X
  375. Xnode    *
  376. Xaddnode(name)
  377. X    register char *name;
  378. X{    register long i;
  379. X    register node *n;
  380. X
  381. X    if (Iflag)
  382. X        lowercase(name);
  383. X
  384. X    /* is it a private host? */
  385. X    n = isprivate(name);
  386. X    if (n)
  387. X        return n;
  388. X
  389. X    i = hash(name, 0);
  390. X    if (Table[i]) 
  391. X        return Table[i];
  392. X
  393. X    n = newnode();
  394. X    n->n_name = strsave(name);
  395. X    Table[i] = n;
  396. X    n->n_tloc = i;    /* essentially a back link to the table */
  397. X
  398. X    return n;
  399. X}
  400. X
  401. Xvoid
  402. Xalias(n1, n2)
  403. X    node *n1, *n2;
  404. X{
  405. X    link    *l;
  406. X
  407. X    if (ISADOMAIN(n1) && ISADOMAIN(n2)) {
  408. X        fprintf(stderr, "%s: domain alias %s = %s is illegal\n", Argv[0], n1->n_name, n2->n_name);
  409. X        return;
  410. X    }
  411. X    l = addlink(n1, n2, (Cost) 0, DEFNET, DEFDIR);
  412. X    l->l_flag |= LALIAS;
  413. X    l = addlink(n2, n1, (Cost) 0, DEFNET, DEFDIR);
  414. X    l->l_flag |= LALIAS;
  415. X    if (Tflag)
  416. X        atrace(n1, n2);
  417. X}
  418. X
  419. X/*
  420. X * fold a string into a long int.  31 bit crc (from andrew appel).
  421. X * the crc table is computed at run time by crcinit() -- we could
  422. X * precompute, but it takes 1 clock tick on a 750.
  423. X *
  424. X * This fast table calculation works only if POLY is a prime polynomial
  425. X * in the field of integers modulo 2.  Since the coefficients of a
  426. X * 32-bit polynomail won't fit in a 32-bit word, the high-order bit is
  427. X * implicit.  IT MUST ALSO BE THE CASE that the coefficients of orders
  428. X * 31 down to 25 are zero.  Happily, we have candidates, from
  429. X * E. J.  Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962):
  430. X *    x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
  431. X *    x^31 + x^3 + x^0
  432. X *
  433. X * We reverse the bits to get:
  434. X *    111101010000000000000000000000001 but drop the last 1
  435. X *         f   5   0   0   0   0   0   0
  436. X *    010010000000000000000000000000001 ditto, for 31-bit crc
  437. X *       4   8   0   0   0   0   0   0
  438. X */
  439. X
  440. X#define POLY32 0xf5000000    /* 32-bit polynomial */
  441. X#define POLY31 0x48000000    /* 31-bit polynomial */
  442. X#define POLY POLY31    /* use 31-bit to avoid sign problems */
  443. X
  444. Xstatic long CrcTable[128];
  445. X
  446. XSTATIC void
  447. Xcrcinit()
  448. X{    register int i,j;
  449. X    register long sum;
  450. X
  451. X    for (i = 0; i < 128; i++) {
  452. X        sum = 0;
  453. X        for (j = 7-1; j >= 0; --j)
  454. X            if (i & (1 << j))
  455. X                sum ^= POLY >> j;
  456. X        CrcTable[i] = sum;
  457. X    }
  458. X}
  459. X
  460. XSTATIC long
  461. Xfold(s)
  462. X    register char *s;
  463. X{    register long sum = 0;
  464. X    register int c;
  465. X
  466. X    while ((c = *s++) != 0)
  467. X        sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
  468. X    return sum;
  469. X}
  470. X
  471. X
  472. X#define HASH1(n) ((n) % Tabsize);
  473. X#define HASH2(n) (Tabsize - 2 - ((n) % (Tabsize-2)))    /* sedgewick */
  474. X
  475. X/*
  476. X * when alpha is 0.79, there should be 2 probes per access (gonnet).
  477. X * use long constant to force promotion.  Tab128 biases HIGHWATER by
  478. X * 128/100 for reduction in strength in isfull().
  479. X */
  480. X#define HIGHWATER    79L
  481. X#define isfull(n)    ((n) * 128 >= Tab128)
  482. X    
  483. XSTATIC long
  484. Xhash(name, unique)
  485. X    char *name;
  486. X    int unique;
  487. X{    register long probe;
  488. X    register long hash2;
  489. X    register node *n;
  490. X
  491. X    if (isfull(Ncount)) {
  492. X        if (Tabsize == 0) {        /* first time */
  493. X            crcinit();
  494. X            Tabindex = 0;
  495. X            Tabsize = Primes[0];
  496. X            Table = newtable(Tabsize);
  497. X            Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
  498. X        } else
  499. X            rehash();        /* more, more! */
  500. X    }
  501. X
  502. X    probe = fold(name);
  503. X    hash2 = HASH2(probe);
  504. X    probe = HASH1(probe);
  505. X
  506. X    /*
  507. X     * probe the hash table.
  508. X     * if unique is set, we require a fresh slot.
  509. X     * otherwise, use double hashing to find either
  510. X     *  (1) an empty slot, or
  511. X     *  (2) a non-private copy of this host name
  512. X     *
  513. X     * this is an "inner loop."
  514. X     */
  515. X    while ((n = Table[probe]) != 0) {
  516. X        if (EQ(n, name) && !(n->n_flag & ISPRIVATE) && !unique)
  517. X            return probe;    /* this is it! */
  518. X
  519. X        probe -= hash2;        /* double hashing */
  520. X        if (probe < 0)
  521. X            probe += Tabsize;
  522. X    }
  523. X    return probe;                    /* brand new */
  524. X}
  525. X
  526. XSTATIC void
  527. Xrehash()
  528. X{    register node **otable, **optr;
  529. X    register long probe;
  530. X    long osize;
  531. X
  532. X#ifdef DEBUG
  533. X    hashanalyze();
  534. X#endif
  535. X    optr = Table + Tabsize - 1;    /* ptr to last */
  536. X    otable = Table;
  537. X    osize = Tabsize;
  538. X    Tabsize = Primes[++Tabindex];
  539. X    if (Tabsize == 0)
  540. X        die("too many hosts");    /* need more prime numbers */
  541. X    vprintf(stderr, "rehash into %d\n", Tabsize);
  542. X    Table = newtable(Tabsize);
  543. X    Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
  544. X
  545. X    do {
  546. X        if (*optr == 0)
  547. X            continue;    /* empty slot in old table */
  548. X        probe = hash((*optr)->n_name,
  549. X            ((*optr)->n_flag & ISPRIVATE) != 0);
  550. X        if (Table[probe] != 0)
  551. X            die("rehash error");
  552. X        Table[probe] = *optr;
  553. X        (*optr)->n_tloc = probe;
  554. X    } while (optr-- > otable);
  555. X    freetable(otable, osize);
  556. X}
  557. X
  558. Xvoid
  559. Xhashanalyze()
  560. X#if 0
  561. X{     long    probe, hash2;
  562. X    int    count, i, collision[8];
  563. X    int    longest = 0, total = 0, slots = 0, longprobe = 0;
  564. X    int    nslots = sizeof(collision)/sizeof(collision[0]);
  565. X
  566. X    if (!Vflag)
  567. X        return;
  568. X
  569. X    strclear((char *) collision, sizeof(collision));
  570. X    for (i = 0; i < Tabsize; i++) {
  571. X        if (Table[i] == 0)
  572. X            continue;
  573. X        /* private hosts too hard to account for ... */
  574. X        if (Table[i]->n_flag & ISPRIVATE)
  575. X            continue;
  576. X        count = 1;
  577. X        probe = fold(Table[i]->n_name);
  578. X        /* don't change the order of the next two lines */
  579. X        hash2 = HASH2(probe);
  580. X        probe = HASH1(probe);
  581. X        /* thank you! */
  582. X        while (Table[probe] != 0
  583. X            && strcmp(Table[probe]->n_name, Table[i]->n_name) != 0) {
  584. X            count++;
  585. X            probe -= hash2;
  586. X            if (probe < 0)
  587. X                probe += Tabsize;
  588. X        }
  589. X        if (Table[probe] == 0)
  590. X            die("impossible hash error");
  591. X        
  592. X        total += count;
  593. X        slots++;
  594. X        if (count > longest) {
  595. X            longest = count;
  596. X            longprobe = i;
  597. X        }
  598. X        if (count >= nslots)
  599. X            count = 0;
  600. X        collision[count]++;
  601. X    }
  602. X    for (i = 1; i < nslots; i++)
  603. X        if (collision[i])
  604. X            fprintf(stderr, "%d chains: %d (%ld%%)\n",
  605. X                i, collision[i], (collision[i] * 100L)/ slots);
  606. X        if (collision[0])
  607. X            fprintf(stderr, "> %d chains: %d (%ld%%)\n",
  608. X                nslots - 1, collision[0],
  609. X                (collision[0] * 100L)/ slots);
  610. X    fprintf(stderr, "%2.2f probes per access, longest chain: %d, %s\n",
  611. X        (double) total / slots, longest, Table[longprobe]->n_name);
  612. X    if (Vflag < 2)
  613. X        return;
  614. X    probe = fold(Table[longprobe]->n_name);
  615. X    hash2 = HASH2(probe);
  616. X    probe = HASH1(probe);
  617. X    while (Table[probe] != 0
  618. X        && strcmp(Table[probe]->n_name, Table[longprobe]->n_name) != 0) {
  619. X        fprintf(stderr, "%5d %s\n", probe, Table[probe]->n_name);
  620. X        probe -= hash2;
  621. X        if (probe < 0)
  622. X            probe += Tabsize;
  623. X    }
  624. X    fprintf(stderr, "%5d %s\n", probe, Table[probe]->n_name);
  625. X    
  626. X}
  627. X#else
  628. X{
  629. X    /* the hash algorithms are perfect -- leave them alone */
  630. X}
  631. X#endif
  632. X
  633. X/* convert to lower case in place */
  634. XSTATIC void
  635. Xlowercase(s)
  636. X    register char *s;
  637. X{
  638. X    do {
  639. X        if (isupper(*s))
  640. X            *s -= 'A' - 'a';    /* ASCII */
  641. X    } while (*s++);
  642. X}
  643. X
  644. X/*
  645. X * this might need change if privates catch on
  646. X */
  647. XSTATIC node *
  648. Xisprivate(name)
  649. X    register char *name;
  650. X{    register node *n;
  651. X
  652. X    for (n = Private; n != 0; n = n->n_private)
  653. X        if (strcmp(name, n->n_name) == 0)
  654. X            return n;
  655. X    return 0;
  656. X}
  657. X
  658. X/*  Add a private node so private that nobody can find it.  */
  659. Xnode *
  660. Xaddhidden(name)
  661. X    register char *name;
  662. X{    register node *n;
  663. X    register int i;
  664. X    if (Iflag)
  665. X        lowercase(name);
  666. X
  667. X    n = newnode();
  668. X    n->n_name = strsave(name);
  669. X    n->n_flag = ISPRIVATE;
  670. X    i = hash(n->n_name, 1);
  671. X    if (Table[i] != 0)
  672. X        die("impossible hidden node error");
  673. X    Table[i] = n;
  674. X    n->n_tloc = i;
  675. X    n->n_private = 0;
  676. X    return n;
  677. X}
  678. X
  679. Xvoid
  680. Xfixprivate()
  681. X{    register node *n, *next;
  682. X    register long i;
  683. X
  684. X    for (n = Private; n != 0; n = next) {
  685. X        n->n_flag |= ISPRIVATE;        /* overkill, but safe */
  686. X        i = hash(n->n_name, 1);
  687. X        if (Table[i] != 0)
  688. X            die("impossible private node error");
  689. X    
  690. X        Table[i] = n;
  691. X        n->n_tloc = i;    /* essentially a back link to the table */
  692. X        next = n->n_private;
  693. X        n->n_private = 0;    /* clear for later use */
  694. X    }
  695. X    Private = 0;
  696. X}
  697. X
  698. Xnode *
  699. Xaddprivate(name)
  700. X    register char *name;
  701. X{    register node *n;
  702. X
  703. X    if (Iflag)
  704. X        lowercase(name);
  705. X    if ((n = isprivate(name)) != 0)
  706. X        return n;
  707. X
  708. X    n = newnode();
  709. X    n->n_name = strsave(name);
  710. X    n->n_private = Private;
  711. X    Private = n;
  712. X    return n;
  713. X}
  714. END_OF_FILE
  715.   if test 8979 -ne `wc -c <'addnode.c'`; then
  716.     echo shar: \"'addnode.c'\" unpacked with wrong size!
  717.   fi
  718.   # end of 'addnode.c'
  719. fi
  720. if test -f 'arpa-privates' -a "${1}" != "-c" ; then 
  721.   echo shar: Will not clobber existing file \"'arpa-privates'\"
  722. else
  723.   echo shar: Extracting \"'arpa-privates'\" \(7927 characters\)
  724.   sed "s/^X//" >'arpa-privates' <<'END_OF_FILE'
  725. X#################################################################
  726. X#    arpa-privates file for arpatxt/pathalias        #
  727. X#                                #
  728. X#    updated from hosts.txt ver. 750 and the            #
  729. X#    UUCP Project map data as of 17-Jun-88            #
  730. X#################################################################
  731. X#    "master" file is available for anonymous ftp at:    #
  732. X#    swan.ulowell.edu:~ftp/hosts/arpa-privates        #
  733. X#    citi.umich.edu:~ftp/pub/honey/arpa-privates        #
  734. X#                                #
  735. X#    Send updates to postmaster at one of above sites.    #
  736. X#################################################################
  737. X#            format:                    #
  738. X#    host    map.file (for registered UUCP hosts)        #
  739. X#    host    [map.file] (for unregistered UUCP hosts)    #
  740. X#    Everything after white space is ignored, and is        #
  741. X#    primarily intended to keep the file easier to update.    #
  742. X#    Order does not matter, but case does.            #
  743. X#################################################################
  744. Xa        usa.ca
  745. Xaardvark    usa.or
  746. Xabbott        usa.ca
  747. Xac1        [usa.ca] nsc
  748. Xac6        [usa.ca] cerebus, esl
  749. Xachilles    [att]
  750. Xacorn        gbr
  751. Xadam        swe
  752. Xadams        swe
  753. Xadmin        usa.ca
  754. Xalamo        usa.tx
  755. Xalex        usa.va
  756. Xalf        [usa.az] ellymae
  757. Xalgedi        [usa.wa] pilchuck
  758. Xalien        usa.ca
  759. Xalpha        usa.in
  760. Xaltair        [usa.tx] juniper
  761. Xamc        usa.wa
  762. Xamos        [usa.ca] suntan
  763. Xandy        [att]
  764. Xantares        usa.nj
  765. Xanubis        usa.il
  766. Xapollo        usa.ma
  767. Xaqua        usa.ma
  768. Xarc        usa.ca
  769. Xares        swe
  770. Xargon        usa.nj
  771. Xargus        usa.nj
  772. Xariadne        grc
  773. Xariel        [usa.oh] mtune-isn
  774. Xaris        grc
  775. Xarthur        [usa.mo] wuphys
  776. Xasgard        usa.or
  777. Xastro        [usa.tx] milano
  778. Xathena        [usa.ca] daisy
  779. Xatlas        [att]
  780. Xatt        
  781. Xb21        deu
  782. Xbacchus        usa.nc
  783. Xbert        usa.ca
  784. Xbezier        [usa.oh] bgsuvax
  785. Xblue        jpn
  786. Xbluto        [usa.tx] im4u
  787. Xbobcat        [usa.ca] vortex
  788. Xboojum        [att]
  789. Xboole        [att]
  790. Xbosco        [esp]
  791. Xbounty        [usa.az] ellymae
  792. Xbourbaki    usa.il
  793. Xbridge        [usa.il] richp1
  794. Xbugs        [usa.ca] cuschico
  795. Xbull        usa.ca
  796. Xcac        usa.ma
  797. Xcad        dmk (ibt)
  798. Xcalico        usa.ny
  799. Xcallisto    usa.in
  800. Xcalvin        [usa.ca] ucdavis
  801. Xcantor        [usa.il] gargoyle, luccpud
  802. Xcarl        swe
  803. Xcarmel        [usa.az] verde
  804. Xcarrara        [usa.ma] talcott
  805. Xcasper        usa.or
  806. Xcastor        [att]
  807. Xccb        [kor] kaist
  808. Xccd        usa.fl (pd1)
  809. Xccs        [usa.tx] convex
  810. Xcerberus    usa.ca
  811. Xchaos        usa.ok
  812. Xcheetah        usa.oh
  813. Xchem        usa.ca
  814. Xcheops        [usa.ca] esl
  815. Xchip        usa.ca
  816. Xchiron        usa.ny
  817. Xchopin        [att]
  818. Xcims1        usa.ga
  819. Xcip        ita
  820. Xcirce        [att]
  821. Xclara        usa.ny
  822. Xclover        usa.ca
  823. Xcls        [usa.nh] sii
  824. Xclutx        [usa.fl] gould
  825. Xcmr        usa.fl
  826. Xcogito        [att]
  827. Xcognac        usa.pa
  828. Xcolby        usa.me
  829. Xcondor        usa.ma
  830. Xcookie        usa.ne
  831. Xcoral        usa.ca
  832. Xcortex        [usa.tx] CNLNET/soma
  833. Xcottage        gbr
  834. Xcrash        usa.ca
  835. Xcs1        usa.ca
  836. Xcsab        [usa.va] xanth, [usa.il] uiucdcs
  837. Xcsc        can.on
  838. Xcsd1        [usa.ny] cmcl2
  839. Xcsd2        [usa.ny] cmcl2
  840. Xcssun        [usa.ny] albanycs
  841. Xcsun1        usa.ga
  842. Xcsun2        usa.ga
  843. Xcti        usa.ca
  844. Xcurie        usa.tx
  845. Xcygnus        usa.ny
  846. Xdalek        usa.ca
  847. Xdali        [esp] goya
  848. Xdarwin        can.on
  849. Xdavid        usa.oh
  850. Xdcn1        [usa.ca] scgvaxd
  851. Xdeimos        [usa.oh] codas
  852. Xdelphi        ita
  853. Xdeneb        [can.bc] ubc-cs
  854. Xdescartes    [usa.ca] nosc
  855. Xdevvax        usa.ny (until Larry fixes news path on jpl-devvax)
  856. Xdewey        [usa.ca] hpda
  857. Xdipl        usa.ca
  858. Xdisc        [usa.ca] ucdavis
  859. Xdorothy        usa.ca
  860. Xdraco        [usa.tx] petro
  861. Xea        usa.ok
  862. Xeagle        [usa.ca] ames
  863. Xearth        [att]
  864. Xeast        fra
  865. Xecn        nld
  866. Xed        gbr
  867. Xedam        [att]
  868. Xedith        [usa.oh] mtune
  869. Xeli        usa.dc
  870. Xelse        jpn
  871. Xelvira        [usa.dc] sundc
  872. Xemily        [usa.nj] althea
  873. Xems        usa.mn
  874. Xernie        usa.ca
  875. Xescher        usa.ca
  876. Xetl        [usa.va] potomac
  877. Xeunice        usa.fl
  878. Xeuropa        usa.ri
  879. Xevans        [usa.ca] ucbvax
  880. Xeve        [usa.ny] clara
  881. Xewok        [usa.nc] suntri
  882. Xfalcon        [usa.nc] suntri
  883. Xfaraday        usa.ny
  884. Xfaust        usa.ma
  885. Xfenway        usa.ga
  886. Xfergvax        [usa.ne] upba
  887. Xfisher        usa.nj
  888. Xflight        [usa.or] argent
  889. Xfluke        usa.wa
  890. Xfoobar        usa.or
  891. Xforest        [usa.tx] hal6000
  892. Xforty2        che
  893. Xfred        usa.co
  894. Xfrisbee        usa.co
  895. Xfrog        usa.ma
  896. Xgaia        usa.co
  897. Xgalaxy        usa.nj
  898. Xgamma        [usa.oh] codas
  899. Xgandalf        can.on
  900. Xgarfield    can.nf
  901. Xgateway        [usa.ut] pedro
  902. Xgemini        usa.ca
  903. Xgeorge        usa.tx
  904. Xgilbert        [usa.wa] pilchuck
  905. Xgizmo        [usa.ca] sun
  906. Xgodot        usa.nc
  907. Xgodzilla    [att]
  908. Xgolem        usa.ca
  909. Xgort        [usa.ok] romed
  910. Xgould        usa.fl
  911. Xgranite        [usa.nh] decvax
  912. Xgreen        [usa.md] jhunix
  913. Xgrendel        [usa.oh] mtune
  914. Xgrinch        usa.ca
  915. Xgroucho        [att]
  916. Xgrumpy        [usa.oh] codas
  917. Xgull        usa.tx
  918. Xhal        usa.oh
  919. Xhamster        [usa.ca] qantel
  920. Xhappy        usa.ca
  921. Xhawk        [usa.ca] nosc
  922. Xhector        [att]
  923. Xhelios        can.on
  924. Xhermes        [att]
  925. Xhollywood    [usa.ca] fortune
  926. Xhottub        usa.ca
  927. Xhq        sgp
  928. Xhub        [usa.ca] comdesign
  929. Xhugo        usa.va
  930. Xhydra        usa.nj
  931. Xhydro        [usa.ca] csustan
  932. Xibd        [att]
  933. Xibis        usa.tx
  934. Xicarus        [usa.ri] brunix
  935. Xice        usa.wi
  936. Ximagen        usa.ca
  937. Xindra        [usa.oh] codas
  938. Xintrepid    usa.ar
  939. Xio        [usa.oh] mtune
  940. Xipac        [usa.az] noao, [usa.ca] csula-ps
  941. Xircam        fra
  942. Xiris        usa.ri
  943. Xisi        usa.ca
  944. Xisis        usa.co
  945. Xisland        usa.ca
  946. Xjack        usa.ca
  947. Xjanus        usa.ca
  948. Xjhereg        [usa.mn] bungia
  949. Xjuniper        usa.tx
  950. Xkaos        usa.ma
  951. Xkiwi        bel
  952. Xkontiki        dmk
  953. Xkronos        grc
  954. Xlafite        [usa.nh] decvax
  955. Xlassen        usa.ca
  956. Xlaura        deu
  957. Xleg        [fra] geocub
  958. Xlego        dmk
  959. Xleopard        [att]
  960. Xlilac        kor
  961. Xlinus        usa.ma
  962. Xlion        [att]
  963. Xlola        [usa.oh] codas
  964. Xlono        usa.ca
  965. Xlynx        usa.ca
  966. Xmacom1        usa.md
  967. Xmagic        [usa.ca] idi
  968. Xmanatee        usa.fl
  969. Xmanta        usa.pa
  970. Xmarge        usa.ca
  971. Xmars        usa.nj
  972. Xmaui        usa.va
  973. Xmax        [att]
  974. Xmaxwell        usa.mo
  975. Xmcl        can.sk
  976. Xmcs        usa.md
  977. Xmedusa        usa.nj
  978. Xmegalon        deu
  979. Xmercury        [usa.ma] interlan
  980. Xmerlin        [usa.ma] masscomp
  981. Xmickey        usa.ca
  982. Xmimas        nld
  983. Xminnie        usa.co
  984. Xmiranda        [usa.oh] mtune
  985. Xmirage        gbr
  986. Xmoe        [usa.nv] jimi
  987. Xmojave        usa.ca
  988. Xmoses        [usa.mi] umich
  989. Xmouse        usa.de
  990. Xmozart        usa.ny
  991. Xmruxd        [att]
  992. Xms        can.on
  993. Xmycroft        [usa.ca] hplabs
  994. Xmyrddin        [usa.ca] amdahl-bartender
  995. Xnetman        [att]
  996. Xnewton        [can.bc] ubc-cs
  997. Xnexus        usa.dc
  998. Xnirvana        usa.va
  999. Xnoether        [usa.ny] mozart
  1000. Xnova        usa.ok
  1001. Xoac        [att]
  1002. Xnps        [usa.il] cerl
  1003. Xnyquiest    [att]
  1004. Xoahu        [usa.nj] hjuxa
  1005. Xoak        [usa.ct] clunker
  1006. Xoasis        usa.ca    (precautionary. llnl clashes with oasis.sait.ko.kr)
  1007. Xocean        [usa.ca] ucsbcsl
  1008. Xodin        [att]
  1009. Xopus        [att]
  1010. Xorbit        usa.mn
  1011. Xorca        [usa.az] ellymae
  1012. Xorcas        usa.wa
  1013. Xoregon        usa.or    {believe it or not}
  1014. Xorion        [att]
  1015. Xorville        usa.ny
  1016. Xoscar        [usa.oh] bcd-dyn
  1017. Xosiris        usa.md
  1018. Xoz        usa.wa
  1019. Xpallas        usa.il
  1020. Xpandora        [usa.ma] harv-net
  1021. Xpegasus        [att]
  1022. Xpercival    usa.or
  1023. Xphobos        usa.vt
  1024. Xphoebus        gbr
  1025. Xphoenix        [att]
  1026. Xphysics        [usa.ny] ccnysci
  1027. Xpicasso        [esp] goya
  1028. Xpilchuck    usa.wa
  1029. Xpioneer        usa.md
  1030. Xpixar        usa.ca
  1031. Xplasma        usa.ca
  1032. Xplato        usa.ca
  1033. Xpluto        usa.ny
  1034. Xpokey        [usa.va] men2a
  1035. Xpolaris        [usa.wa] camco
  1036. Xpollux        usa.tx
  1037. Xpostel        nld
  1038. Xpresto        usa.md
  1039. Xpriam        [che] cernvax
  1040. Xprime        usa.ma
  1041. Xprism        usa.nj
  1042. Xprodigal    usa.pa
  1043. Xprometheus    usa.md
  1044. Xpsc        usa.md
  1045. Xpsych        [aus]
  1046. Xpsyche        usa.nc
  1047. Xpuppy        usa.ny
  1048. Xqat        [usa.tx] techsup
  1049. Xquark        [usa.ca] csuchico
  1050. Xra        [can.bc] ubc-cs
  1051. Xrainier        swe
  1052. Xralph        usa.la
  1053. Xrdm        usa.ga
  1054. Xreason        usa.ny
  1055. Xrebel        usa.ga
  1056. Xred        jpn
  1057. Xredwood        [usa.ca] amdcad
  1058. Xridge        usa.ca
  1059. Xrobin        [usa.oh] bgsuvax [usa.ma] linus
  1060. Xrodan        usa.or
  1061. Xrome        usa.ok
  1062. Xrosetta        [usa.tx] rice
  1063. Xrover        [usa.az] ellymae
  1064. Xrsch        [usa.ma] harvard
  1065. Xsable        [usa.ca] pyramid
  1066. Xsabre        [usa.oh] codas
  1067. Xsal        swe
  1068. Xsam        usa.il
  1069. Xsandy        [usa.tx] woton
  1070. Xsas        [usa.nc] rti
  1071. Xsaturn        [kor] ketri
  1072. Xscarecrow    [usa.pa] lehi3b15
  1073. Xscooter        usa.ca
  1074. Xselect        nld
  1075. Xservice        gbr
  1076. Xshamash        usa.mn
  1077. Xshaw        [att]
  1078. Xshockeye    usa.pa
  1079. Xshrike        [usa.tx] MBIRNET
  1080. Xshrimp        usa.tx
  1081. Xsierra        usa.ca
  1082. Xsimon        usa.il
  1083. Xsirius        [usa.nh] dartvax
  1084. Xsmith        [can.ab] edm
  1085. Xsnark        usa.pa
  1086. Xsnucom        kor
  1087. Xsol        usa.nh
  1088. Xsolar        usa.nm
  1089. Xsoleil        usa.nj
  1090. Xspam        usa.nj
  1091. Xsparky        [usa.oh] codas
  1092. Xsphinx        usa.il
  1093. Xspike        usa.la
  1094. Xspock        usa.ct
  1095. Xsri        aus.qld
  1096. Xssi        usa.wi
  1097. Xstar        [usa.oh] codas
  1098. Xstars        [can.ns] dalcs
  1099. Xstuart        [usa.md] prometheus
  1100. Xstymie        [usa.ma] harvard
  1101. Xsuna        [usa.mn] mscunx
  1102. Xsunburn        usa.az
  1103. Xsunrise        usa.nj
  1104. Xsunspot        usa.nm
  1105. Xsuntan        usa.ca
  1106. Xsunup        usa.wa
  1107. Xsuper        usa.md
  1108. Xsvc        [usa.md] epiwrl
  1109. Xswamp        [usa.ca] amdahl
  1110. Xswan        usa.tx
  1111. Xtaurus        isr
  1112. Xte        gbr
  1113. Xterminus    [att]
  1114. Xthermo        [usa.nv] stride1
  1115. Xthor        dmk
  1116. Xthunder        can.on
  1117. Xtiger        usa.nj
  1118. Xtinman        usa.ca
  1119. Xtitan        usa.ca
  1120. Xtrantor        usa.ca
  1121. Xtut        fin
  1122. Xubvax        usa.ca
  1123. Xunh        usa.nh
  1124. Xunix        usa.wa
  1125. Xusafa        [usa.co] winfree, [usa.fl] gould, [usa.nh] trixie
  1126. Xvalhalla    [usa.mi] edsr
  1127. Xvax2        [usa.md] elsie
  1128. Xvector        usa.tx
  1129. Xvice        [usa.or] enky, budda, loop
  1130. Xvideo        [att]
  1131. Xvilya        [att]
  1132. Xviper        [usa.mn] bungia, mmm, pwcs, quest
  1133. Xvista        usa.ca
  1134. Xvlsi1        [usa.ut] byuopus
  1135. Xvlsi2        [usa.ut] byuopus
  1136. Xvlsi3        [usa.ut] byuopus
  1137. Xvolt        usa.ca
  1138. Xvoodoo        usa.wa
  1139. Xwang        usa.ma
  1140. Xwayback        [att]
  1141. Xwombat        usa.ca
  1142. Xwotan        usa.ca
  1143. Xxyzzy        usa.nc
  1144. Xyoda        usa.co (UCARNET)
  1145. Xyogi        [usa.nj] bellcore-micom, pyrnj
  1146. Xz        usa.ca
  1147. Xzap        can.qc
  1148. Xzaphod        can.sk
  1149. Xzeta        [usa.md] cp1
  1150. Xzeus        can.bc
  1151. Xzip        usa.oh
  1152. Xzorac        can.on
  1153. END_OF_FILE
  1154.   if test 7927 -ne `wc -c <'arpa-privates'`; then
  1155.     echo shar: \"'arpa-privates'\" unpacked with wrong size!
  1156.   fi
  1157.   # end of 'arpa-privates'
  1158. fi
  1159. if test -f 'mapaux.c' -a "${1}" != "-c" ; then 
  1160.   echo shar: Will not clobber existing file \"'mapaux.c'\"
  1161. else
  1162.   echo shar: Extracting \"'mapaux.c'\" \(8512 characters\)
  1163.   sed "s/^X//" >'mapaux.c' <<'END_OF_FILE'
  1164. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  1165. X#ifndef lint
  1166. Xstatic char    *sccsid = "@(#)mapaux.c    9.4 89/03/01";
  1167. X#endif /* lint */
  1168. X
  1169. X#include "def.h"
  1170. X
  1171. X/* imports */
  1172. Xextern long Nheap, Hashpart, Tabsize, NumNcopy, Nlink, NumLcopy;
  1173. Xextern node **Table, *Home;
  1174. Xextern char *Graphout, *Linkout, *Netchars, **Argv;
  1175. Xextern int Vflag;
  1176. Xextern void freelink(), die();
  1177. Xextern long pack();
  1178. Xextern link *newlink();
  1179. Xextern node *newnode();
  1180. Xextern char *strsave();
  1181. Xextern int strcmp(), strlen();
  1182. X
  1183. X/* exports */
  1184. Xextern long pack();
  1185. Xextern void resetnodes(), dumpgraph(), showlinks(), terminalnet();
  1186. Xextern int tiebreaker();
  1187. Xextern node *ncopy();
  1188. X
  1189. X/* privates */
  1190. Xstatic FILE *Gstream;    /* for dumping graph */
  1191. XSTATIC void dumpnode(), untangle(), dfs();
  1192. XSTATIC int height();
  1193. XSTATIC link *lcopy();
  1194. X
  1195. X
  1196. X/*
  1197. X * slide everything from Table[low] to Table[high]
  1198. X * up toward the high end.  make room!  make room!
  1199. X */
  1200. Xlong
  1201. Xpack(low, high)
  1202. X    long low, high;
  1203. X{    long hole, next;
  1204. X
  1205. X    /* find first "hole " */
  1206. X    for (hole = high; hole >= low && Table[hole] != 0; --hole)
  1207. X        ;
  1208. X
  1209. X    /* repeatedly move next filled entry into last hole */
  1210. X    for (next = hole - 1; next >= low; --next) {
  1211. X        if (Table[next] != 0) {
  1212. X            Table[hole] = Table[next];
  1213. X            Table[hole]->n_tloc = hole;
  1214. X            Table[next] = 0;
  1215. X            while (Table[--hole] != 0)    /* find next hole */
  1216. X                ;
  1217. X        }
  1218. X    }
  1219. X    return hole + 1;
  1220. X}
  1221. X
  1222. Xvoid
  1223. Xresetnodes()
  1224. X{    register long i;
  1225. X    register node *n;
  1226. X
  1227. X    for (i = Hashpart; i < Tabsize; i++)
  1228. X        if ((n = Table[i]) != 0) {
  1229. X            n->n_cost = (Cost) 0;
  1230. X            n->n_flag &= ~(NALIAS|ATSIGN|MAPPED|HASLEFT|HASRIGHT|NTERMINAL);
  1231. X            n->n_copy = n;
  1232. X        }
  1233. X        
  1234. X    Home->n_cost = (Cost) 0;
  1235. X    Home->n_flag &= ~(NALIAS|ATSIGN|MAPPED|HASLEFT|HASRIGHT|NTERMINAL);
  1236. X    Home->n_copy = Home;
  1237. X}
  1238. X
  1239. Xvoid    
  1240. Xdumpgraph()
  1241. X{    register long i;
  1242. X    register node *n;
  1243. X
  1244. X    if ((Gstream = fopen(Graphout, "w")) == NULL) {
  1245. X        fprintf(stderr, "%s: ", Argv[0]);
  1246. X        perror(Graphout);
  1247. X        return;
  1248. X    }
  1249. X
  1250. X    untangle();    /* untangle net cycles for proper output */
  1251. X
  1252. X    for (i = Hashpart; i < Tabsize; i++) {
  1253. X        n = Table[i];
  1254. X        if (n == 0)
  1255. X            continue;    /* impossible, but ... */
  1256. X        /* a minor optimization ... */
  1257. X        if (n->n_link == 0)
  1258. X            continue;
  1259. X        /* pathparse doesn't need these */
  1260. X        if (n->n_flag & NNET)
  1261. X            continue;
  1262. X        dumpnode(n);
  1263. X    }
  1264. X}
  1265. X
  1266. XSTATIC void
  1267. Xdumpnode(from)
  1268. X    register node *from;
  1269. X{    register node *to;
  1270. X    register link *l;
  1271. X    link *lnet = 0, *ll, *lnext;
  1272. X
  1273. X    for (l = from->n_link ; l; l = l->l_next) {
  1274. X        to = l->l_to;
  1275. X        if (from == to)
  1276. X            continue;    /* oops -- it's me! */
  1277. X
  1278. X        if ((to->n_flag & NNET) == 0) {
  1279. X            /* host -> host -- print host>host */
  1280. X            if (l->l_cost == INF)
  1281. X                continue;    /* phoney link */
  1282. X            fputs(from->n_name, Gstream);
  1283. X            putc('>', Gstream);
  1284. X            fputs(to->n_name, Gstream);
  1285. X            putc('\n', Gstream);
  1286. X        } else {
  1287. X            /*
  1288. X             * host -> net -- just cache it for now.
  1289. X             * first check for dups.  (quadratic, but
  1290. X             * n is small here.)
  1291. X             */
  1292. X            while (to->n_root && to != to->n_root)
  1293. X                to = to->n_root;
  1294. X            for (ll = lnet; ll; ll = ll->l_next)
  1295. X                if (strcmp(ll->l_to->n_name, to->n_name) == 0)
  1296. X                    break;
  1297. X            if (ll)
  1298. X                continue;    /* dup */
  1299. X            ll = newlink();
  1300. X            ll->l_next = lnet;
  1301. X            ll->l_to = to;
  1302. X            lnet = ll;
  1303. X        }
  1304. X    }
  1305. X
  1306. X    /* dump nets */
  1307. X    if (lnet) {
  1308. X        /* nets -- print host@\tnet,net, ... */
  1309. X        fputs(from->n_name, Gstream);
  1310. X        putc('@', Gstream);
  1311. X        putc('\t', Gstream);
  1312. X        for (ll = lnet; ll; ll = lnext) {
  1313. X            lnext = ll->l_next;
  1314. X            fputs(ll->l_to->n_name, Gstream);
  1315. X            if (lnext)
  1316. X                fputc(',', Gstream);
  1317. X            freelink(ll);
  1318. X        }
  1319. X        putc('\n', Gstream);
  1320. X    }
  1321. X}
  1322. X
  1323. X/*
  1324. X * remove cycles in net definitions. 
  1325. X *
  1326. X * depth-first search
  1327. X *
  1328. X * for each net, run dfs on its neighbors (nets only).  if we return to
  1329. X * a visited node, that's a net cycle.  mark the cycle with a pointer
  1330. X * in the n_root field (which gets us closer to the root of this
  1331. X * portion of the dfs tree).
  1332. X */
  1333. XSTATIC void
  1334. Xuntangle()
  1335. X{    register long i;
  1336. X    register node *n;
  1337. X
  1338. X    for (i = Hashpart; i < Tabsize; i++) {
  1339. X        n = Table[i];
  1340. X        if (n == 0 || (n->n_flag & NNET) == 0 || n->n_root)
  1341. X            continue;
  1342. X        dfs(n);
  1343. X    }
  1344. X}
  1345. X
  1346. XSTATIC void
  1347. Xdfs(n)
  1348. X    register node *n;
  1349. X{    register link *l;
  1350. X    register node *next;
  1351. X
  1352. X    n->n_flag |= INDFS;
  1353. X    n->n_root = n;
  1354. X    for (l = n->n_link; l; l = l->l_next) {
  1355. X        next = l->l_to;
  1356. X        if ((next->n_flag & NNET) == 0)
  1357. X            continue;
  1358. X        if ((next->n_flag & INDFS) == 0) {
  1359. X            dfs(next);
  1360. X            if (next->n_root != next)
  1361. X                n->n_root = next->n_root;
  1362. X        } else
  1363. X            n->n_root = next->n_root;
  1364. X    }
  1365. X    n->n_flag &= ~INDFS;
  1366. X}
  1367. X
  1368. Xvoid
  1369. Xshowlinks() 
  1370. X{    register link *l;
  1371. X    register node *n;
  1372. X    register long i;
  1373. X    FILE    *estream;
  1374. X
  1375. X    if ((estream = fopen(Linkout, "w")) == 0)
  1376. X        return;
  1377. X
  1378. X    for (i = Hashpart; i < Tabsize; i++) {
  1379. X        n = Table[i];
  1380. X        if (n == 0 || n->n_link == 0)
  1381. X            continue;
  1382. X        for (l = n->n_link; l; l = l->l_next) {
  1383. X            fputs(n->n_name, estream);
  1384. X            putc('\t', estream);
  1385. X            if (NETDIR(l) == LRIGHT)
  1386. X                putc(NETCHAR(l), estream);
  1387. X            fputs(l->l_to->n_name, estream);
  1388. X            if (NETDIR(l) == LLEFT)
  1389. X                putc(NETCHAR(l), estream);
  1390. X            fprintf(estream, "(%d)\n", l->l_cost);
  1391. X        }
  1392. X    }
  1393. X    (void) fclose(estream);
  1394. X}
  1395. X
  1396. X/*
  1397. X * n is node in heap, newp is candidate for new parent.
  1398. X * choose between newp and n->n_parent for parent.
  1399. X * return 0 to use newp, non-zero o.w.
  1400. X */
  1401. X#define NEWP 0
  1402. X#define OLDP 1
  1403. Xint
  1404. Xtiebreaker(n, newp)
  1405. X    node *n;
  1406. X    register node *newp;
  1407. X{    register char *opname, *npname, *name;
  1408. X    register node *oldp;
  1409. X    int metric;
  1410. X
  1411. X    oldp = n->n_parent;
  1412. X
  1413. X    /* given the choice, avoid gatewayed nets */
  1414. X    if (GATEWAYED(newp) && !GATEWAYED(oldp))
  1415. X        return OLDP;
  1416. X    if (!GATEWAYED(newp) && GATEWAYED(oldp))
  1417. X        return NEWP;
  1418. X
  1419. X    /* look at real parents, not nets */
  1420. X    while ((oldp->n_flag & NNET) && oldp->n_parent)
  1421. X        oldp = oldp->n_parent;
  1422. X    while ((newp->n_flag & NNET) && newp->n_parent)
  1423. X        newp = newp->n_parent;
  1424. X
  1425. X    /* use fewer hops, if possible */
  1426. X    metric = height(oldp) - height(newp);
  1427. X    if (metric < 0)
  1428. X        return OLDP;
  1429. X    if (metric > 0)
  1430. X        return NEWP;
  1431. X
  1432. X    /*
  1433. X     * compare names
  1434. X     */
  1435. X    opname = oldp->n_name;
  1436. X    npname = newp->n_name;
  1437. X    name = n->n_name;
  1438. X
  1439. X    /* use longest common prefix with parent */
  1440. X    while (*opname == *name && *npname == *name && *name) {
  1441. X        opname++;
  1442. X        npname++;
  1443. X        name++;
  1444. X    }
  1445. X    if (*opname == *name)
  1446. X        return OLDP;
  1447. X    if (*npname == *name)
  1448. X        return NEWP;
  1449. X
  1450. X    /* use shorter host name */
  1451. X    metric = strlen(opname) - strlen(npname);
  1452. X    if (metric < 0)
  1453. X        return OLDP;
  1454. X    if (metric > 0)
  1455. X        return NEWP;
  1456. X
  1457. X    /* use larger lexicographically */
  1458. X    metric = strcmp(opname, npname);
  1459. X    if (metric < 0)
  1460. X        return NEWP;
  1461. X    return OLDP;
  1462. X}
  1463. X
  1464. XSTATIC int
  1465. Xheight(n)
  1466. X    register node *n;
  1467. X{    register int i = 0;
  1468. X
  1469. X    if (n == 0)
  1470. X        return 0;
  1471. X    while ((n = n->n_parent) != 0)
  1472. X        if (ISADOMAIN(n) || !(n->n_flag & NNET))
  1473. X            i++;
  1474. X    return i;
  1475. X}
  1476. X    
  1477. X/*
  1478. X * return a copy of n ( == l->l_to).  we rely on n and its copy
  1479. X * pointing to the same name string, which is kludgey, but works
  1480. X * because the name is non-volatile.
  1481. X */
  1482. X
  1483. X#define REUSABLE(n, l)    (((n)->n_flag & NTERMINAL) == 0 \
  1484. X              && ((n)->n_copy->n_flag & NTERMINAL) \
  1485. X              && !((n)->n_copy->n_flag & NALIAS) \
  1486. X              && !((l)->l_flag & LALIAS))
  1487. Xnode *
  1488. Xncopy(parent, l)
  1489. X    register node *parent;
  1490. X    register link *l;
  1491. X{    register node *n, *ncp;
  1492. X
  1493. X#ifdef DEBUG
  1494. X    if (Vflag > 1)
  1495. X        vprintf(stderr, "<%s> <- %s\n", l->l_to->n_name, parent->n_name);
  1496. X#endif
  1497. X    n = l->l_to;
  1498. X    if (REUSABLE(n, l)) {
  1499. X        Nlink++;
  1500. X        return n->n_copy;    /* re-use */
  1501. X    }
  1502. X    NumNcopy++;
  1503. X    l->l_to = ncp = newnode();
  1504. X    ncp->n_name = n->n_name;    /* nonvolatile */
  1505. X    ncp->n_tloc = --Hashpart;    /* better not be > 20% of total ... */
  1506. X    if (Hashpart == Nheap)
  1507. X        die("too many terminal links");
  1508. X    Table[Hashpart] = ncp;
  1509. X    ncp->n_copy = n->n_copy;    /* circular list */
  1510. X    n->n_copy = ncp;
  1511. X    ncp->n_link = lcopy(parent, n);
  1512. X    ncp->n_flag = (n->n_flag & ~(NALIAS|ATSIGN|MAPPED|HASLEFT|HASRIGHT)) | NTERMINAL;
  1513. X    return ncp;
  1514. X}
  1515. X
  1516. X/*
  1517. X * copy l, but don't include any links to parent.
  1518. X *
  1519. X * this is a little messier than it should be, because
  1520. X * of the funny test for ancestry, and because it wants
  1521. X * to be recursive, but the recursion might be very deep
  1522. X * (for a long link list), so it's done iteratively.
  1523. X */
  1524. XSTATIC link *
  1525. Xlcopy(parent, n)
  1526. X    register node *parent, *n;
  1527. X{    register link *l, *lcp;
  1528. X    link *first = 0, *last = 0;
  1529. X    for (l = n->n_link; l != 0; l = l->l_next) {
  1530. X        /* avoid vestigial descendants */
  1531. X        if ((l->l_to->n_flag & MAPPED) != 0
  1532. X         || ALTEREGO(l->l_to, parent))
  1533. X            continue;
  1534. X#ifdef DEBUG
  1535. X        if (Vflag > 1)
  1536. X            vprintf(stderr, "\t-> %s\n", l->l_to->n_name);
  1537. X#endif
  1538. X        NumLcopy++;
  1539. X        lcp = newlink();
  1540. X        *lcp = *l;    /* struct copy */
  1541. X        lcp->l_flag &= ~LTREE;
  1542. X        if (ISANET(n))
  1543. X            lcp->l_flag |= LTERMINAL;
  1544. X        if (first == 0) {
  1545. X            first = last = lcp;
  1546. X        } else {
  1547. X            last->l_next = lcp;
  1548. X            last = lcp;
  1549. X        }
  1550. X    }
  1551. X    if (last)
  1552. X        last->l_next = 0;
  1553. X    return first;
  1554. X}
  1555. END_OF_FILE
  1556.   if test 8512 -ne `wc -c <'mapaux.c'`; then
  1557.     echo shar: \"'mapaux.c'\" unpacked with wrong size!
  1558.   fi
  1559.   # end of 'mapaux.c'
  1560. fi
  1561. if test -f 'parse.y' -a "${1}" != "-c" ; then 
  1562.   echo shar: Will not clobber existing file \"'parse.y'\"
  1563. else
  1564.   echo shar: Extracting \"'parse.y'\" \(10671 characters\)
  1565.   sed "s/^X//" >'parse.y' <<'END_OF_FILE'
  1566. X%{
  1567. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  1568. X#ifndef lint
  1569. Xstatic char    *sccsid = "@(#)parse.y    9.10 88/09/07";
  1570. X#endif /* lint */
  1571. X
  1572. X#include "def.h"
  1573. X
  1574. X/* scanner states (yylex, parse) */
  1575. X#define OTHER        0
  1576. X#define COSTING        1
  1577. X#define NEWLINE        2
  1578. X#define FILENAME    3
  1579. X
  1580. X/* exports */
  1581. Xlong Tcount;
  1582. Xextern void yyerror();
  1583. X
  1584. X/* imports */
  1585. Xextern node *addnode(), *addprivate();
  1586. Xextern void fixprivate(), alias(), deadlink(), deletelink();
  1587. Xextern link *addlink();
  1588. Xextern int strcmp();
  1589. Xextern char *strsave();
  1590. Xextern int optind;
  1591. Xextern char *Cfile, *Netchars, **Argv;
  1592. Xextern int Lineno, Argc;
  1593. X
  1594. X/* privates */
  1595. XSTATIC void fixnet(), adjust();
  1596. XSTATIC int yylex(), yywrap(), getword();
  1597. Xstatic int Scanstate = NEWLINE;    /* scanner (yylex) state */
  1598. X
  1599. X/* flags for ys_flags */
  1600. X#define TERMINAL 1
  1601. X%}
  1602. X
  1603. X%union {
  1604. X    node    *y_node;
  1605. X    Cost    y_cost;
  1606. X    char    y_net;
  1607. X    char    *y_name;
  1608. X    struct {
  1609. X        node *ys_node;
  1610. X        Cost ys_cost;
  1611. X        short ys_flag;
  1612. X        char ys_net;
  1613. X        char ys_dir;
  1614. X    } y_s;
  1615. X}
  1616. X
  1617. X%type <y_s>    site asite
  1618. X%type <y_node>    links aliases plist network nlist host nhost
  1619. X%type <y_node>    usite delem dlist
  1620. X%type <y_cost>    cost cexpr
  1621. X
  1622. X%token <y_name>    SITE HOST STRING
  1623. X%token <y_cost>    COST
  1624. X%token <y_net>    NET
  1625. X%token EOL PRIVATE DEAD DELETE FILETOK ADJUST
  1626. X
  1627. X%left    '+' '-'
  1628. X%left    '*' '/'
  1629. X
  1630. X%%
  1631. Xmap    :    /* empty */
  1632. X    |    map        EOL
  1633. X    |    map links    EOL
  1634. X    |    map aliases    EOL
  1635. X    |    map network    EOL
  1636. X    |    map private    EOL
  1637. X    |    map dead    EOL
  1638. X    |    map delete    EOL
  1639. X    |    map file    EOL
  1640. X    |    map adjust    EOL
  1641. X    |    error        EOL
  1642. X    ;
  1643. X
  1644. Xlinks    : host site cost {
  1645. X        struct link *l;
  1646. X
  1647. X        l = addlink($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
  1648. X        if (GATEWAYED($2.ys_node))
  1649. X            l->l_flag |= LGATEWAY;
  1650. X        if ($2.ys_flag & TERMINAL)
  1651. X            l->l_flag |= LTERMINAL;
  1652. X      }            
  1653. X    | links ',' site cost {
  1654. X        struct link *l;
  1655. X
  1656. X        l = addlink($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
  1657. X        if (GATEWAYED($3.ys_node))
  1658. X            l->l_flag |= LGATEWAY;
  1659. X        if ($3.ys_flag & TERMINAL)
  1660. X            l->l_flag |= LTERMINAL;
  1661. X      }
  1662. X    | links ','    /* benign error */
  1663. X    ;
  1664. X
  1665. Xhost    : HOST        {$$ = addnode($1);}
  1666. X    | PRIVATE    {$$ = addnode("private");}
  1667. X    | DEAD        {$$ = addnode("dead");}
  1668. X    | DELETE    {$$ = addnode("delete");}
  1669. X    | FILETOK    {$$ = addnode("file");}
  1670. X    | ADJUST    {$$ = addnode("adjust");}
  1671. X    ;
  1672. X
  1673. Xsite    : asite {
  1674. X        $$ = $1;
  1675. X        $$.ys_net = DEFNET;
  1676. X        $$.ys_dir = DEFDIR;
  1677. X      }
  1678. X    | NET asite {
  1679. X        $$ = $2;
  1680. X        $$.ys_net = $1;
  1681. X        $$.ys_dir = LRIGHT;
  1682. X      }
  1683. X    | asite NET {
  1684. X        $$ = $1;
  1685. X        $$.ys_net = $2;
  1686. X        $$.ys_dir = LLEFT;
  1687. X      }
  1688. X    ;
  1689. X
  1690. Xasite    : SITE {
  1691. X        $$.ys_node = addnode($1);
  1692. X        $$.ys_flag = 0;
  1693. X      }
  1694. X    | '<' SITE '>' {
  1695. X        Tcount++;
  1696. X        $$.ys_node = addnode($2);
  1697. X        $$.ys_flag = TERMINAL;
  1698. X      }
  1699. X    ;
  1700. X
  1701. Xaliases    : host '=' SITE    {alias($1, addnode($3));}
  1702. X    | aliases ',' SITE    {alias($1, addnode($3));}
  1703. X    | aliases ','    /* benign error */
  1704. X    ;
  1705. X
  1706. Xnetwork    : nhost '{' nlist '}' cost    {fixnet($1, $3, $5, DEFNET, DEFDIR);}
  1707. X    | nhost NET '{' nlist '}' cost    {fixnet($1, $4, $6, $2, LRIGHT);}
  1708. X    | nhost '{' nlist '}' NET cost    {fixnet($1, $3, $6, $5, LLEFT);}
  1709. X    ;
  1710. X
  1711. Xnhost    : '='        {$$ = 0;    /* anonymous net */}
  1712. X    | host '='    {$$ = $1;    /* named net */}
  1713. X    ;
  1714. X
  1715. Xnlist    : SITE        {$$ = addnode($1);}
  1716. X    | nlist ',' SITE {
  1717. X        node *n;
  1718. X
  1719. X        n = addnode($3);
  1720. X        if (n->n_net == 0) {
  1721. X            n->n_net = $1;
  1722. X            $$ = n;
  1723. X        }
  1724. X      }
  1725. X    | nlist ','    /* benign error */
  1726. X    ;
  1727. X        
  1728. Xprivate    : PRIVATE '{' plist '}'            /* list of privates */
  1729. X    | PRIVATE '{' '}'    {fixprivate();}    /* end scope of privates */
  1730. X    ;
  1731. X
  1732. Xplist    : SITE            {addprivate($1)->n_flag |= ISPRIVATE;}
  1733. X    | plist ',' SITE    {addprivate($3)->n_flag |= ISPRIVATE;}
  1734. X    | plist ','        /* benign error */
  1735. X    ;
  1736. X
  1737. Xdead    : DEAD '{' dlist '}';
  1738. X
  1739. Xdlist    : delem
  1740. X    | dlist ',' delem
  1741. X    | dlist ','        /* benign error */
  1742. X    ;
  1743. X
  1744. Xdelem    : SITE            {deadlink(addnode($1), (node *) 0);}
  1745. X    | usite NET usite    {deadlink($1, $3);}
  1746. X    ;
  1747. X
  1748. Xusite    : SITE    {$$ = addnode($1);} ;    /* necessary unit production */
  1749. X
  1750. Xdelete    : DELETE '{' dellist '}';
  1751. X
  1752. Xdellist    : delelem
  1753. X    | dellist ',' delelem
  1754. X    | dellist ','        /* benign error */
  1755. X    ;
  1756. X
  1757. Xdelelem    : SITE {
  1758. X        node *n;
  1759. X
  1760. X        n = addnode($1);
  1761. X        deletelink(n, (node *) 0);
  1762. X        n->n_flag |= ISPRIVATE;
  1763. X      }
  1764. X    | usite NET usite    {deletelink($1, $3);}
  1765. X    ;
  1766. X
  1767. Xfile    : FILETOK '{' {Scanstate = FILENAME;} STRING {Scanstate = OTHER;} '}' {
  1768. X        Lineno = 0;
  1769. X        Cfile = strsave($4);
  1770. X    }
  1771. X
  1772. Xadjust    : ADJUST '{' adjlist '}' ;
  1773. X
  1774. Xadjlist    : adjelem
  1775. X    | adjlist ',' adjelem
  1776. X    | adjlist ','        /* benign error */
  1777. X    ;
  1778. X
  1779. Xadjelem    : usite cost    {adjust($1, $2);} ;
  1780. X
  1781. Xcost    : {$$ = DEFCOST;    /* empty -- cost is always optional */}
  1782. X    | '(' {Scanstate = COSTING;} cexpr {Scanstate = OTHER;} ')'
  1783. X        {$$ = $3;}
  1784. X    ;
  1785. X
  1786. Xcexpr    : COST
  1787. X    | '-' cexpr      {$$ = -$2;}
  1788. X    | '(' cexpr ')'   {$$ = $2;}
  1789. X    | cexpr '+' cexpr {$$ = $1 + $3;}
  1790. X    | cexpr '-' cexpr {$$ = $1 - $3;}
  1791. X    | cexpr '*' cexpr {$$ = $1 * $3;}
  1792. X    | cexpr '/' cexpr {
  1793. X        if ($3 == 0)
  1794. X            yyerror("zero divisor\n");
  1795. X        else
  1796. X            $$ = $1 / $3;
  1797. X      }
  1798. X    ;
  1799. X%%
  1800. X
  1801. Xvoid
  1802. X#ifdef YYDEBUG
  1803. X/*VARARGS1*/
  1804. Xyyerror(fmt, arg)
  1805. X    char *fmt, *arg;
  1806. X#else
  1807. Xyyerror(s)
  1808. X    char *s;
  1809. X#endif
  1810. X{
  1811. X    /* a concession to bsd error(1) */
  1812. X    fprintf(stderr, "\"%s\", ", Cfile);
  1813. X#ifdef YYDEBUG
  1814. X    fprintf(stderr, "line %d: ", Lineno);
  1815. X    fprintf(stderr, fmt, arg);
  1816. X    putc('\n', stderr);
  1817. X#else
  1818. X    fprintf(stderr, "line %d: %s\n", Lineno, s);
  1819. X#endif
  1820. X}
  1821. X
  1822. X/*
  1823. X * patch in the costs of getting on/off the network.
  1824. X *
  1825. X * for each network member on netlist, add links:
  1826. X *    network -> member    cost = 0;
  1827. X *    member -> network    cost = parameter.
  1828. X *
  1829. X * if network and member both require gateways, assume network
  1830. X * is a gateway to member (but not v.v., to avoid such travesties
  1831. X * as topaz!seismo.css.gov.edu.rutgers).
  1832. X *
  1833. X * note that members can have varying costs to a network, by suitable
  1834. X * multiple declarations.  this is a feechur, albeit a useless one.
  1835. X */
  1836. XSTATIC void
  1837. Xfixnet(network, nlist, cost, netchar, netdir)
  1838. X    register node *network;
  1839. X    node *nlist;
  1840. X    Cost cost;
  1841. X    char netchar, netdir;
  1842. X{    register node *member, *nextnet;
  1843. X    link *l;
  1844. X    static int netanon = 0;
  1845. X    char anon[25];
  1846. X
  1847. X    if (network == 0) {
  1848. X        sprintf(anon, "[unnamed net %d]", netanon++);
  1849. X        network = addnode(anon);
  1850. X    }
  1851. X    network->n_flag |= NNET;
  1852. X
  1853. X    /* insert the links */
  1854. X    for (member = nlist ; member; member = nextnet) {
  1855. X
  1856. X        /* network -> member, cost is 0 */
  1857. X        l = addlink(network, member, (Cost) 0, netchar, netdir);
  1858. X        if (GATEWAYED(network) && GATEWAYED(member))
  1859. X            l->l_flag |= LGATEWAY;
  1860. X
  1861. X        /* member -> network, cost is parameter */
  1862. X        /* never ever ever crawl up from a domain*/
  1863. X        if (!ISADOMAIN(network))
  1864. X            (void) addlink(member, network, cost, netchar, netdir);
  1865. X
  1866. X        nextnet = member->n_net;
  1867. X        member->n_net = 0;    /* clear for later use */
  1868. X    }
  1869. X}
  1870. X
  1871. X/* scanner */
  1872. X
  1873. X#define QUOTE '"'
  1874. X#define STR_EQ(s1, s2) (s1[2] == s2[2] && strcmp(s1, s2) == 0)
  1875. X#define NLRETURN() {Scanstate = NEWLINE; return EOL;}
  1876. X
  1877. Xstatic struct ctable {
  1878. X    char *cname;
  1879. X    Cost cval;
  1880. X} ctable[] = {
  1881. X    /* ordered by frequency of appearance in a "typical" dataset */
  1882. X    {"DIRECT", 200},
  1883. X    {"DEMAND", 300},
  1884. X    {"DAILY", 5000},
  1885. X    {"HOURLY", 500},
  1886. X    {"DEDICATED", 100},
  1887. X    {"EVENING", 2000},
  1888. X    {"LOCAL", 25},
  1889. X    {"LOW", 5},    /* baud rate, quality penalty */
  1890. X    {"DEAD", MILLION},
  1891. X    {"POLLED", 5000},
  1892. X    {"WEEKLY", 30000},
  1893. X    {"HIGH", -5},    /* baud rate, quality bonus */
  1894. X    {"FAST", -80},    /* high speed (>= 9.6 kbps) modem */
  1895. X    /* deprecated */
  1896. X    {"ARPA", 100},
  1897. X    {"DIALED", 300},
  1898. X    {0, 0}
  1899. X};
  1900. X
  1901. XSTATIC int
  1902. Xyylex()
  1903. X{    static char retbuf[128];    /* for return to yacc part */
  1904. X    register int c;
  1905. X    register char *buf = retbuf;
  1906. X    register struct ctable *ct;
  1907. X    register Cost cost;
  1908. X    char errbuf[128];
  1909. X
  1910. X    if (feof(stdin) && yywrap())
  1911. X        return EOF;
  1912. X
  1913. X    /* count lines, skip over space and comments */
  1914. X    if ((c = getchar()) == EOF)
  1915. X        NLRETURN();
  1916. X    
  1917. Xcontinuation:
  1918. X    while (c == ' ' || c == '\t')
  1919. X        if ((c = getchar()) == EOF)
  1920. X            NLRETURN();
  1921. X
  1922. X    if (c == '#')
  1923. X        while ((c = getchar()) != '\n')
  1924. X            if (c == EOF)
  1925. X                NLRETURN();
  1926. X
  1927. X    /* scan token */
  1928. X    if (c == '\n') {
  1929. X        Lineno++;
  1930. X        if ((c = getchar()) != EOF) {
  1931. X            if (c == ' ' || c == '\t')
  1932. X                goto continuation;
  1933. X            ungetc(c, stdin);
  1934. X        }
  1935. X        NLRETURN();
  1936. X    }
  1937. X
  1938. X    switch(Scanstate) {
  1939. X    case COSTING:
  1940. X        if (isdigit(c)) {
  1941. X            cost = c - '0';
  1942. X            for (c = getchar(); isdigit(c); c = getchar())
  1943. X                cost = (cost * 10) + c - '0';
  1944. X            ungetc(c, stdin);
  1945. X            yylval.y_cost = cost;
  1946. X            return COST;
  1947. X        }
  1948. X
  1949. X        if (getword(buf, c) == 0) {
  1950. X            for (ct = ctable; ct->cname; ct++)
  1951. X                if (STR_EQ(buf, ct->cname)) {
  1952. X                    yylval.y_cost = ct->cval;
  1953. X                    return COST;
  1954. X                }
  1955. X            sprintf(errbuf, "unknown cost (%s), using default", buf);
  1956. X            yyerror(errbuf);
  1957. X            yylval.y_cost = DEFCOST;
  1958. X            return COST;
  1959. X        }
  1960. X
  1961. X        return c;    /* pass the buck */
  1962. X
  1963. X    case NEWLINE:
  1964. X        Scanstate = OTHER;
  1965. X        if (getword(buf, c) != 0)
  1966. X            return c;
  1967. X        /*
  1968. X         * special purpose tokens.
  1969. X         *
  1970. X         * the "switch" serves the dual-purpose of recognizing
  1971. X         * unquoted tokens only.
  1972. X         */
  1973. X        switch(c) {
  1974. X        case 'p':
  1975. X            if (STR_EQ(buf, "private"))
  1976. X                return PRIVATE;
  1977. X            break;
  1978. X        case 'd':
  1979. X            if (STR_EQ(buf, "dead"))
  1980. X                return DEAD;
  1981. X            if (STR_EQ(buf, "delete"))
  1982. X                return DELETE;
  1983. X            break;
  1984. X        case 'f':
  1985. X            if (STR_EQ(buf, "file"))
  1986. X                return FILETOK;
  1987. X            break;
  1988. X        case 'a':
  1989. X            if (STR_EQ(buf, "adjust"))
  1990. X                return ADJUST;
  1991. X            break;
  1992. X        }
  1993. X
  1994. X        yylval.y_name = buf;
  1995. X        return HOST;
  1996. X
  1997. X    case FILENAME:
  1998. X        while (c != EOF && isprint(c)) {
  1999. X            if (c == ' ' || c == '\t' || c == '\n' || c == '}')
  2000. X                break;
  2001. X            *buf++ = c;
  2002. X            c = getchar();
  2003. X        }
  2004. X        if (c != EOF)
  2005. X            ungetc(c, stdin);
  2006. X        *buf = 0;
  2007. X        yylval.y_name = retbuf;
  2008. X        return STRING;
  2009. X    }
  2010. X
  2011. X    if (getword(buf, c) == 0) {
  2012. X        yylval.y_name = buf;
  2013. X        return SITE;
  2014. X    }
  2015. X
  2016. X    if (index(Netchars, c)) {
  2017. X        yylval.y_net = c;
  2018. X        return NET;
  2019. X    }
  2020. X
  2021. X    return c;
  2022. X}
  2023. X
  2024. X/*
  2025. X * fill str with the next word in [0-9A-Za-z][-._0-9A-Za-z]+ or a quoted
  2026. X * string that contains no newline.  return -1 on failure or EOF, 0 o.w.
  2027. X */ 
  2028. XSTATIC int
  2029. Xgetword(str, c)
  2030. X    register char *str;
  2031. X    register int c;
  2032. X{
  2033. X    if (c == QUOTE) {
  2034. X        while ((c = getchar()) != QUOTE) {
  2035. X            if (c == '\n') {
  2036. X                yyerror("newline in quoted string\n");
  2037. X                ungetc(c, stdin);
  2038. X                return -1;
  2039. X            }
  2040. X            if (c == EOF) {
  2041. X                yyerror("EOF in quoted string\n");
  2042. X                return -1;
  2043. X            }
  2044. X            *str++ = c;
  2045. X        }
  2046. X        *str = 0;
  2047. X        return 0;
  2048. X    }
  2049. X
  2050. X    /* host name must start with alphanumeric or `.' */
  2051. X    if (!isalnum(c) && c != '.')
  2052. X        return -1;
  2053. X
  2054. Xyymore:
  2055. X    do {
  2056. X        *str++ = c;
  2057. X        c = getchar();
  2058. X    } while (isalnum(c) || c == '.' || c == '_');
  2059. X
  2060. X    if (c == '-' && Scanstate != COSTING)
  2061. X        goto yymore;
  2062. X
  2063. X    ungetc(c, stdin);
  2064. X    *str = 0;
  2065. X    return 0;
  2066. X}
  2067. X
  2068. XSTATIC int
  2069. Xyywrap()
  2070. X{    char errbuf[100];
  2071. X
  2072. X    fixprivate();    /* munge private host definitions */
  2073. X    Lineno = 1;
  2074. X    while (optind < Argc) {
  2075. X        if (freopen((Cfile = Argv[optind++]), "r", stdin) != 0)
  2076. X            return 0;
  2077. X        sprintf(errbuf, "%s: %s", Argv[0], Cfile);
  2078. X        perror(errbuf);
  2079. X    }
  2080. X    freopen("/dev/null", "r", stdin);
  2081. X    return -1;
  2082. X}
  2083. X
  2084. XSTATIC void
  2085. Xadjust(n, cost)
  2086. X    node *n;
  2087. X    Cost cost;
  2088. X{    link *l;
  2089. X
  2090. X    n->n_cost += cost;    /* cumulative */
  2091. X
  2092. X    /* hit existing links */
  2093. X    for (l = n->n_link; l; l = l->l_next) {
  2094. X        if ((l->l_cost += cost) < 0) {
  2095. X            char buf[100];
  2096. X
  2097. X            l->l_flag |= LDEAD;
  2098. X            sprintf(buf, "link to %s deleted with negative cost",
  2099. X                            l->l_to->n_name);
  2100. X            yyerror(buf);
  2101. X        }
  2102. X    }
  2103. X}
  2104. END_OF_FILE
  2105.   if test 10671 -ne `wc -c <'parse.y'`; then
  2106.     echo shar: \"'parse.y'\" unpacked with wrong size!
  2107.   fi
  2108.   # end of 'parse.y'
  2109. fi
  2110. if test -f 'printit.c' -a "${1}" != "-c" ; then 
  2111.   echo shar: Will not clobber existing file \"'printit.c'\"
  2112. else
  2113.   echo shar: Extracting \"'printit.c'\" \(6907 characters\)
  2114.   sed "s/^X//" >'printit.c' <<'END_OF_FILE'
  2115. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  2116. X#ifndef lint
  2117. Xstatic char    *sccsid = "@(#)printit.c    9.4 89/02/07";
  2118. X#endif
  2119. X
  2120. X#include "def.h"
  2121. X
  2122. X/*
  2123. X * print the routes by traversing the shortest path tree in preorder.
  2124. X * use lots of char bufs -- profiling indicates this costs about 5 kbytes
  2125. X */
  2126. X
  2127. X/* exports */
  2128. Xextern void printit();
  2129. X
  2130. X/* imports */
  2131. Xextern int Cflag, Vflag, Dflag, Fflag;
  2132. Xextern node *Home;
  2133. Xextern char *Netchars;
  2134. Xextern void die();
  2135. Xextern int strlen();
  2136. X
  2137. X/* privates */
  2138. Xstatic link *Ancestor;    /* for -f option */
  2139. XSTATIC void preorder(), setpath(), printhost(), printdomain();
  2140. XSTATIC char *hostpath();
  2141. XSTATIC int printable();
  2142. X
  2143. X/* in practice, even the longest paths are < 100 bytes */
  2144. X#define PATHSIZE 512
  2145. X
  2146. Xvoid
  2147. Xprintit()
  2148. X{    link *l;
  2149. X    char pbuf[PATHSIZE];
  2150. X
  2151. X    /* print home */
  2152. X    if (Cflag)
  2153. X        printf("%ld\t", (long) Home->n_cost);
  2154. X    printf("%s\t%%s\n", Home->n_name);
  2155. X    
  2156. X    strcpy(pbuf, "%s");
  2157. X    for (l = Home->n_link; l; l = l->l_next) {
  2158. X        if (l->l_flag & LTREE) {
  2159. X            l->l_flag &= ~LTREE;
  2160. X            Ancestor = l;
  2161. X            preorder(l, pbuf);
  2162. X            strcpy(pbuf, "%s");
  2163. X        }
  2164. X    }
  2165. X    fflush(stdout);
  2166. X    fflush(stderr);
  2167. X}
  2168. X
  2169. X/*
  2170. X * preorder traversal of shortest path tree.
  2171. X */
  2172. XSTATIC void
  2173. Xpreorder(l, ppath)
  2174. X    register link *l;
  2175. X    char *ppath;
  2176. X{    register node *n;
  2177. X    node *ncp;        /* circular copy list */
  2178. X    Cost cost;
  2179. X    char npath[PATHSIZE];
  2180. X    short p_dir;        /* DIR bits of parent (for nets) */
  2181. X    char p_op;        /* net op of parent (for nets) */
  2182. X
  2183. X    setpath(l, ppath, npath);
  2184. X    n = l->l_to;
  2185. X    if (printable(n)) {
  2186. X        if (Fflag)
  2187. X            cost = Ancestor->l_to->n_cost;
  2188. X        else
  2189. X            cost = n->n_cost;
  2190. X        if (ISADOMAIN(n))
  2191. X            printdomain(n, npath, cost);
  2192. X        else if (!(n->n_flag & NNET)) {
  2193. X            printhost(n, npath, cost);
  2194. X        }
  2195. X        n->n_flag |= PRINTED;
  2196. X        for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy)
  2197. X            ncp->n_flag |= PRINTED;
  2198. X    }
  2199. X
  2200. X    /* prepare routing bits for domain members */
  2201. X    p_dir = l->l_flag & LDIR;
  2202. X    p_op = l->l_netop;
  2203. X
  2204. X    /* recursion */
  2205. X    for (l = n->n_link; l; l = l->l_next) {
  2206. X        if (!(l->l_flag & LTREE))
  2207. X            continue;
  2208. X        /* network member inherits the routing syntax of its gateway */
  2209. X        if (ISANET(n)) {
  2210. X            l->l_flag = (l->l_flag & ~LDIR) | p_dir;
  2211. X            l->l_netop = p_op;
  2212. X        }
  2213. X        l->l_flag &= ~LTREE;
  2214. X        preorder(l, npath);
  2215. X    }
  2216. X}
  2217. X
  2218. XSTATIC int
  2219. Xprintable(n)
  2220. X    register node *n;
  2221. X{    node *ncp;
  2222. X    link *l;
  2223. X
  2224. X    if (n->n_flag & PRINTED)
  2225. X        return 0;
  2226. X
  2227. X    /* is there a cheaper copy? */
  2228. X    for (ncp = n->n_copy; n != ncp; ncp = ncp->n_copy) {
  2229. X        if (!(ncp->n_flag & MAPPED))
  2230. X            continue;    /* unmapped copy */
  2231. X
  2232. X        if (n->n_cost > ncp->n_cost)
  2233. X            return 0;    /* cheaper copy */
  2234. X
  2235. X        if (n->n_cost == ncp->n_cost && !(ncp->n_flag & NTERMINAL))
  2236. X            return 0;    /* synthetic copy */
  2237. X    }
  2238. X
  2239. X    /* will a domain route suffice? */
  2240. X    if (Dflag && !ISANET(n) && ISADOMAIN(n->n_parent)) {
  2241. X        /*
  2242. X         * are there any interesting links?  a link
  2243. X         * is interesting if it doesn't point back
  2244. X         * to the parent, and is not an alias.
  2245. X         */
  2246. X
  2247. X        /* check n */
  2248. X        for (l = n->n_link; l; l = l->l_next) {
  2249. X            if (l->l_to == n->n_parent)
  2250. X                continue;
  2251. X            if (!(l->l_flag & LALIAS))
  2252. X                return 1;
  2253. X        }
  2254. X
  2255. X        /* check copies of n */
  2256. X        for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy) {
  2257. X            for (l = ncp->n_link; l; l = l->l_next) {
  2258. X                if (l->l_to == n->n_parent)
  2259. X                    continue;
  2260. X                if (!(l->l_flag & LALIAS))
  2261. X                    return 1;
  2262. X            }
  2263. X        }
  2264. X
  2265. X        /* domain route suffices */
  2266. X        return 0;
  2267. X    }
  2268. X    return 1;
  2269. X}
  2270. X
  2271. XSTATIC void
  2272. Xsetpath(l, ppath, npath) 
  2273. X    link *l;
  2274. X    register char *ppath, *npath;
  2275. X{    register node *next, *parent;
  2276. X    char netchar;
  2277. X
  2278. X    next = l->l_to;
  2279. X    parent = next->n_parent;
  2280. X    netchar = NETCHAR(l);
  2281. X
  2282. X    /* for magic @->% conversion */
  2283. X    if (parent->n_flag & ATSIGN)
  2284. X        next->n_flag |= ATSIGN;
  2285. X
  2286. X    /*
  2287. X     * i've noticed that distant gateways to domains frequently get
  2288. X     * ...!gateway!user@dom.ain wrong.  ...!gateway!user%dom.ain
  2289. X     * seems to work, so if next is a domain and the parent is
  2290. X     * not the local host, force a magic %->@ conversion.  in this
  2291. X     * context, "parent" is the nearest ancestor that is not a net.
  2292. X     */
  2293. X    while (ISANET(parent))
  2294. X        parent = parent->n_parent;
  2295. X    if (ISADOMAIN(next) && parent != Home)
  2296. X        next->n_flag |= ATSIGN;
  2297. X
  2298. X    /*
  2299. X     * special handling for nets (including domains) and aliases.
  2300. X     * part of the trick is to treat aliases to domains as 0 cost
  2301. X     * links.  (the author believes they should be declared as such
  2302. X     * in the input, but the world disagrees).
  2303. X     */
  2304. X    if (ISANET(next) || ((l->l_flag & LALIAS) && !ISADOMAIN(parent))) {
  2305. X        strcpy(npath, ppath);
  2306. X        return;
  2307. X    }
  2308. X        
  2309. X    if (netchar == '@')
  2310. X        if (next->n_flag & ATSIGN)
  2311. X            netchar = '%';    /* shazam?  shaman? */
  2312. X        else
  2313. X            next->n_flag |= ATSIGN;
  2314. X
  2315. X    /* remainder should be a sprintf -- foo on '%' as an operator */
  2316. X    for ( ; (*npath = *ppath) != 0; ppath++) {
  2317. X        if (*ppath == '%') {
  2318. X            switch(ppath[1]) {
  2319. X            case 's':
  2320. X                ppath++;
  2321. X                npath = hostpath(npath, l, netchar);
  2322. X                break;
  2323. X
  2324. X            case '%':
  2325. X                *++npath = *++ppath;
  2326. X                npath++;
  2327. X                break;
  2328. X
  2329. X            default:
  2330. X                die("unknown escape in setpath");
  2331. X                break;
  2332. X            }
  2333. X        } else
  2334. X            npath++;
  2335. X    }
  2336. X}
  2337. X
  2338. XSTATIC char *
  2339. Xhostpath(path, l, netchar)
  2340. X    register char *path;
  2341. X    register link *l;
  2342. X    char netchar;
  2343. X{    register node *prev;
  2344. X
  2345. X    prev = l->l_to->n_parent;
  2346. X    if (NETDIR(l) == LLEFT) {
  2347. X        /* host!%s */
  2348. X        strcpy(path, l->l_to->n_name);
  2349. X        path += strlen(path);
  2350. X        while (ISADOMAIN(prev)) {
  2351. X            strcpy(path, prev->n_name);
  2352. X            path += strlen(path);
  2353. X            prev = prev->n_parent;
  2354. X        }
  2355. X        *path++ = netchar;
  2356. X        if (netchar == '%')
  2357. X            *path++ = '%';
  2358. X        *path++ = '%';
  2359. X        *path++ = 's';
  2360. X    } else {
  2361. X        /* %s@host */
  2362. X        *path++ = '%';
  2363. X        *path++ = 's';
  2364. X        *path++ = netchar;
  2365. X        if (netchar == '%')
  2366. X            *path++ = '%';
  2367. X        strcpy(path, l->l_to->n_name);
  2368. X        path += strlen(path);
  2369. X        while (ISADOMAIN(prev)) {
  2370. X            strcpy(path, prev->n_name);
  2371. X            path += strlen(path);
  2372. X            prev = prev->n_parent;
  2373. X        }
  2374. X    }
  2375. X    return path;
  2376. X}
  2377. X
  2378. XSTATIC void
  2379. Xprinthost(n, path, cost)
  2380. X    register node *n;
  2381. X    char *path;
  2382. X    Cost cost;
  2383. X{
  2384. X    if (n->n_flag & PRINTED)
  2385. X        die("printhost called twice");
  2386. X    n->n_flag |= PRINTED;
  2387. X    /* skip private hosts */
  2388. X    if ((n->n_flag & ISPRIVATE) == 0) {
  2389. X        if (Cflag)
  2390. X            printf("%ld\t", (long) cost);
  2391. X        fputs(n->n_name, stdout);
  2392. X        putchar('\t');
  2393. X        puts(path);
  2394. X    }
  2395. X}
  2396. X
  2397. XSTATIC void
  2398. Xprintdomain(n, path, cost)
  2399. X    register node *n;
  2400. X    char *path;
  2401. X    Cost cost;
  2402. X{    node *p;
  2403. X
  2404. X    if (n->n_flag & PRINTED)
  2405. X        die("printdomain called twice");
  2406. X    n->n_flag |= PRINTED;
  2407. X
  2408. X    /*
  2409. X     * print a route for dom.ain if it is a top-level domain, unless
  2410. X     * it is private.
  2411. X     *
  2412. X     * print a route for sub.dom.ain only if all its ancestor dom.ains
  2413. X     * are private and sub.dom.ain is not private.
  2414. X     */
  2415. X    if (!ISADOMAIN(n->n_parent)) {
  2416. X        /* top-level domain */
  2417. X        if (n->n_flag & ISPRIVATE) {
  2418. X            vprintf(stderr, "ignoring private top-level domain %s\n", n->n_name);
  2419. X            return;
  2420. X        }
  2421. X    } else {
  2422. X        /* subdomain */
  2423. X        for (p = n->n_parent; ISADOMAIN(p); p = p->n_parent)
  2424. X            if (!(p->n_flag & ISPRIVATE))
  2425. X                return;
  2426. X        if (n->n_flag & ISPRIVATE)
  2427. X            return;
  2428. X    }
  2429. X
  2430. X    /* print it (at last!) */
  2431. X    if (Cflag)
  2432. X        printf("%ld\t", (long) cost);
  2433. X    do {
  2434. X        fputs(n->n_name, stdout);
  2435. X        n = n->n_parent;
  2436. X    } while (ISADOMAIN(n));
  2437. X    putchar('\t');
  2438. X    puts(path);
  2439. X}
  2440. END_OF_FILE
  2441.   if test 6907 -ne `wc -c <'printit.c'`; then
  2442.     echo shar: \"'printit.c'\" unpacked with wrong size!
  2443.   fi
  2444.   # end of 'printit.c'
  2445. fi
  2446. echo shar: End of archive 2 \(of 3\).
  2447. cp /dev/null ark2isdone
  2448. MISSING=""
  2449. for I in 1 2 3 ; do
  2450.     if test ! -f ark${I}isdone ; then
  2451.     MISSING="${MISSING} ${I}"
  2452.     fi
  2453. done
  2454. if test "${MISSING}" = "" ; then
  2455.     echo You have unpacked all 3 archives.
  2456.     rm -f ark[1-9]isdone
  2457. else
  2458.     echo You still must unpack the following archives:
  2459.     echo "        " ${MISSING}
  2460. fi
  2461. exit 0
  2462. exit 0 # Just in case...
  2463.